package com.example.testdemo.db;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

import com.example.testdemo.MainActivity;
import com.example.testdemo.db.sql.ResultHandler;

import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.locks.ReentrantLock;

/**
 * <p>
 * 顶层Dao 封装 数据库连接
 * </p>
 *
 * @author 永健
 * @since 2020-03-27 17:27
 */
public abstract class BaseDb<T> extends SQLiteOpenHelper {


    protected volatile static int CONNECT_CONNECT = 0;

    private static final ReentrantLock lock = new ReentrantLock(true);

    private volatile static SQLiteDatabase database;
    private volatile static boolean isLock = false;

    private static List<String> CREATE_TABLE_SQL = new ArrayList<>();

    private Class<T> t;

    public BaseDb(String name, int version) {
        super(MainActivity.context, name, null, version);
        this.saveTableSql();
        this.t = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
    }

    protected abstract String createTableSql();

    private void saveTableSql() {
        CREATE_TABLE_SQL.add(createTableSql());
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        while (CreateTableSignal.isStartFinish()) {
            for (String sql : CREATE_TABLE_SQL) {
                db.execSQL(sql);
            }
            return;
        }
    }


    long insert(String tableName, ContentValues contentValues) {
        long insert = 0;
        try {
            getDatabase(true).insert(tableName, null, contentValues);
            submitTransation();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            endTransaction();
            closeConnect();
        }
        return insert;
    }

    List<T> query(String sql, String[] params) {
        Cursor cursor = null;
        List<T> list = new ArrayList<>();
        try {
            cursor = getDatabase(false).rawQuery(sql, params);
            list = new ResultHandler<T>(this.t).resultEntity(sql, cursor);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            cursor.close();
            endTransaction();
            closeConnect();
        }
        return list;
    }

    List<Map<String, Object>> queryMap(String sql, String[] params) {
        Cursor cursor = null;
        List<Map<String, Object>> maps = new ArrayList<>();
        try {
            cursor = getDatabase(false).rawQuery(sql, params);
            maps = new ResultHandler<T>(t).resultMap(sql, cursor);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            cursor.close();
            endTransaction();
            closeConnect();
        }
        return maps;
    }


    void execute(String sql) {
        try {
            String aCase = sql.toLowerCase();
            boolean lock = false;
            if (aCase.contains("update") || aCase.contains("delete") || aCase.contains("insert")) {
                lock = true;
            }
            getDatabase(lock).execSQL(sql);
            submitTransation();
        } catch (SQLException e) {
            e.printStackTrace();
            throw new SQLException();
        } finally {
            endTransaction();
            closeConnect();
        }
    }

    private void setLock(boolean isWrite) {
        // 是否写操作
        if (isWrite) {
            lock.lock();
            System.out.println("写操作");
            isLock = true;
        } else {
            // 当前有正在写的操作
            if (isLock) {
                lock.lock();
                isLock = true;
            } else {
                isLock = false;
            }
            System.out.println("读操作");
        }
    }

    private SQLiteDatabase getDatabase(boolean isWrite) {

        ++CONNECT_CONNECT;
        //System.out.println("当前连接数：" + (CONNECT_CONNECT));
        setLock(isWrite);
        try {
            if (database == null || !database.isOpen()) {
                database = getWritableDatabase();
            }
            beginTransation();
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("获取数据库连接失败:" + e.getMessage());
        } finally {
        }
        return database;
    }

    void closeConnect() {
        try {
//            System.out.println("释放锁");
            lock.unlock();
            isLock = false;
        } catch (Exception e) {
        }
        --CONNECT_CONNECT;
        System.out.println("-");
        // System.out.println("当前连接数-：" + CONNECT_CONNECT);
    }

    void beginTransation() {
        if (database != null) {
            database.beginTransaction();
        }
    }

    void submitTransation() {
        if (database != null) {
            database.setTransactionSuccessful();
        }
    }

    void endTransaction() {
        if (database != null) {
            database.endTransaction();
        }
    }


}
